﻿using Super.Admin.IServices;
using System.Collections;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Super.Admin.ViewModels.Base
{
    public abstract class ViewModelBase : INotifyPropertyChanged, ICloseable, IParameterReceiver, INotifyDataErrorInfo, IDisposable
    {
        public event PropertyChangedEventHandler PropertyChanged; // 属性改变事件
        public event EventHandler Closed; // 关闭事件
        public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged; // 数据校验事件
        /// <summary>
        /// 对话框返回结果
        /// </summary>
        public Dictionary<string, object> DialogResult { get; } = new Dictionary<string, object>();
        /// <summary>
        /// 属性改变通知
        /// </summary>
        /// <param name="propertyName"></param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        /// <summary>
        /// 关闭对话框
        /// </summary>
        public virtual void Close()
        {
            Closed?.Invoke(this, EventArgs.Empty);
        }
        /// <summary>
        /// 接受参数
        /// </summary>
        /// <param name="parameters"></param>
        public virtual void ReceiveParameters(Dictionary<string, object> parameters) { }
        /// <summary>
        /// 初始化参数
        /// </summary>
        public virtual void InitModifyParameters() { }
        /// <summary>
        /// 设置属性值并通知更改
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="field"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        #region INotifyDataErrorInfo 验证信息
        /// <summary>
        /// 存储属性的错误信息
        /// </summary>
        protected readonly Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
        public bool HasErrors => _errors.Count > 0; // 是否存在错误
        /// <summary>
        /// 获取指定属性的错误信息
        /// </summary>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public IEnumerable GetErrors(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName) || !_errors.ContainsKey(propertyName))
                return null;
            return _errors[propertyName];
        }
        /// <summary>
        /// 添加错误信息
        /// </summary>
        /// <param name="errorMessage"></param>
        /// <param name="propertyName"></param>
        protected void AddError(string errorMessage, [CallerMemberName] string propertyName = null)
        {
            if (!_errors.ContainsKey(propertyName))
                _errors[propertyName] = new List<string>();

            if (!_errors[propertyName].Contains(errorMessage))
            {
                _errors[propertyName].Add(errorMessage);
                OnErrorsChanged(propertyName);
            }
        }
        /// <summary>
        /// 清除指定属性的错误信息
        /// </summary>
        /// <param name="propertyName"></param>
        protected void ClearErrors([CallerMemberName] string propertyName = null)
        {
            if (_errors.Remove(propertyName))
            {
                OnErrorsChanged(propertyName);
            }
        }
        /// <summary>
        /// 触发错误信息改变事件
        /// </summary>
        /// <param name="propertyName"></param>
        protected void OnErrorsChanged(string propertyName)
        {
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
            OnPropertyChanged(nameof(HasErrors));
        }
        private bool _isValid;
        /// <summary>
        /// 内容是否有效
        /// </summary>
        public bool IsValid
        {
            get => _isValid;
            set
            {
                SetProperty<bool>(ref _isValid, value);
            }
        }
        /// <summary>
        /// 验证内容的有效性
        /// </summary>
        public virtual void ValidateContent() => IsValid = !HasErrors;
        /// <summary>
        /// 清除释放
        /// </summary>
        public virtual void Dispose() { }
        #endregion
    }
}
